//
// Created by pzw on 23-12-29.
//

#include <QLabel>
#include <QLineEdit>
#include <QTextEdit>
#include <QPushButton>
#include <QVBoxLayout>
#include <QComboBox>
#include <QtWidgets>
#include <iostream>
#include "CommunityCan.h"
#include "../so/ECanVci.h"

//接口卡类型定义
#define USBCAN1 3
#define USBCAN2 4
//函数调用返回状态值
#define STATUS_OK 1
#define STATUS_ERR 0

//通道号 @{
#define CAN1 0
#define CAN2 1
// @}

static DWORD DeviceType = USBCAN2; //设备类型 USBCAN2 双通道
static DWORD DeviceInd = 0; //设备索引 0，只有一个 USBCAN

CommunityCan::CommunityCan(QWidget *parent, QFlags<Qt::WindowType> name) : QMainWindow(parent, name) {
    this->setWindowTitle("CommunityCan");
    // 创建布局，这里一定要按照我的时序和依赖关系进行操作，否则界面会错乱
    QWidget *widget = new QWidget(this);
    setCentralWidget(widget);
    QVBoxLayout *layout = new QVBoxLayout(widget);

    // 创建发送方式下拉选择框
    QLabel *sendModeLabel = new QLabel("发送方式:", widget);
    QComboBox *sendModeComboBox = new QComboBox(widget);
    sendModeComboBox->addItem("正常发送");
    sendModeComboBox->addItem("单次发送");
    sendModeComboBox->addItem("自发自收");
    layout->addWidget(sendModeLabel);
    layout->addWidget(sendModeComboBox);

    // 创建帧类型下拉选择框
    QLabel *frameTypeLabel = new QLabel("帧类型:", widget);
    QComboBox *frameTypeComboBox = new QComboBox(widget);
    frameTypeComboBox->addItem("数据帧");
    frameTypeComboBox->addItem("远程帧");
    layout->addWidget(frameTypeLabel);
    layout->addWidget(frameTypeComboBox);

    // 创建帧格式下拉选择框
    QLabel *frameFormatLabel = new QLabel("帧格式:", widget);
    QComboBox *frameFormatComboBox = new QComboBox(widget);
    frameFormatComboBox->addItem("标准帧");
    frameFormatComboBox->addItem("扩展帧");
    layout->addWidget(frameFormatLabel);
    layout->addWidget(frameFormatComboBox);

    // 创建可以输入的帧ID控件
    QLabel *frameIdLabel = new QLabel("帧ID:", widget);
    QLineEdit *frameIdLineEdit = new QLineEdit(widget);
    layout->addWidget(frameIdLabel);
    layout->addWidget(frameIdLineEdit);

    // 创建可以输入的帧长度控件
    QLabel *frameLengthLabel = new QLabel("帧长度:", widget);
    QLineEdit *frameLengthLineEdit = new QLineEdit(widget);
    layout->addWidget(frameLengthLabel);
    layout->addWidget(frameLengthLineEdit);

    // 创建可以输入的帧数据控件
    QLabel *frameDataLabel = new QLabel("帧数据:", widget);
    QTextEdit *frameDataTextEdit = new QTextEdit(widget);
    layout->addWidget(frameDataLabel);
    layout->addWidget(frameDataTextEdit);

    // 创建可以输入的发送次数控件
    QLabel *sendCountLabel = new QLabel("发送次数:", widget);
    QLineEdit *sendCountLineEdit = new QLineEdit(widget);
    layout->addWidget(sendCountLabel);
    layout->addWidget(sendCountLineEdit);

    // 创建可以输入的发送间隔控件
    QLabel *sendIntervalLabel = new QLabel("发送间隔(ms):", widget);
    QLineEdit *sendIntervalLineEdit = new QLineEdit(widget);
    layout->addWidget(sendIntervalLabel);
    layout->addWidget(sendIntervalLineEdit);

    // 创建发送按钮
    QPushButton *sendButton = new QPushButton("开始发送", widget);
    layout->addWidget(sendButton);

    // 创建停止发送按钮
    QPushButton *stopButton = new QPushButton("停止发送", widget);
    layout->addWidget(stopButton);
    this->setLayout(layout);

    // 连接发送按钮的点击事件
    connect(
            sendButton,
            &QPushButton::clicked,
            this,
            [
                    this,
                    sendModeComboBox,
                    frameTypeComboBox,
                    frameFormatComboBox,
                    frameIdLineEdit,
                    frameLengthLineEdit,
                    frameDataTextEdit,
                    sendCountLineEdit,
                    sendIntervalLineEdit
            ]() {
                // 获取用户输入的数据并执行发送操作
                QString sendMode = sendModeComboBox->currentText();
                QString frameType = frameTypeComboBox->currentText();
                QString frameFormat = frameFormatComboBox->currentText();
                QString frameId = frameIdLineEdit->text();
                QString frameLength = frameLengthLineEdit->text();
                QString frameData = frameDataTextEdit->toPlainText();
                QString sendCount = sendCountLineEdit->text();
                QString sendInterval = sendIntervalLineEdit->text();

                // 执行发送操作
                sendFrames(
                        sendMode,
                        frameType,
                        frameFormat,
                        frameId,
                        frameLength,
                        frameData,
                        sendCount,
                        sendInterval
                );
            }
    );

    // 连接停止发送按钮的点击事件
    connect(stopButton, &QPushButton::clicked, this, [this]() {
        // 执行停止发送操作
        stopSending();
    });
    resize(1280, 720);
}

CommunityCan::~CommunityCan() {

}

/**
 * 获取发送模式
 *
 * @param str qt选中的字符串
 * @return
 */
static int getSendMode(const QString &str) {
    if (str == "正常发送") {
        return 0;
    } else if (str == "单次发送") {
        return 1;
    } else if (str == "自发自收") {
        return 2;
    } else if (str == "自发自收") {
        return 3;
    } else {
        // 如果输入的字符串不匹配任何映射关系，可以返回一个默认值或抛出异常
        return 0;
    }
}

/**
 * 获取帧类型
 *
 * @param str qt选中的字符串
 * @return
 */
static int getFrameType(const QString &str) {
    if (str == "数据帧") {
        return 0;
    } else if (str == "远程帧") {
        return 1;
    } else {
        // 如果输入的字符串不匹配任何映射关系，可以返回一个默认值或抛出异常
        return 0;
    }
}

/**
 * 桢格式
 *
 * @param str qt选中的字符串
 * @return
 */
static int getFrameFormat(const QString &str) {
    if (str == "标准帧") {
        return 0;
    } else if (str == "扩展帧") {
        return 1;
    } else {
        // 如果输入的字符串不匹配任何映射关系，可以返回一个默认值或抛出异常
        return 0;
    }
}

/**
 * 打印CAN_OBJ
 *
 * @param obj - CAN_OBJ
 */
void print_CAN_Obj(const CAN_OBJ &obj) {
    std::cout << "CAN_OBJ:" << std::endl;
    std::cout << "ID: " << obj.ID << std::endl;
    std::cout << "TimeStamp: " << obj.TimeStamp << std::endl;
    std::cout << "TimeFlag: " << static_cast<int>(obj.TimeFlag) << std::endl;
    std::cout << "SendType: " << static_cast<int>(obj.SendType) << std::endl;
    std::cout << "RemoteFlag: " << static_cast<int>(obj.RemoteFlag) << std::endl;
    std::cout << "ExternFlag: " << static_cast<int>(obj.ExternFlag) << std::endl;
    std::cout << "DataLen: " << static_cast<int>(obj.DataLen) << std::endl;
    std::cout << "Data: ";
    for (int i = 0; i < 8; i++) {
        std::cout << static_cast<int>(obj.Data[i]) << " ";
    }
    std::cout << std::endl;
    std::cout << "Reserved: ";
    for (int i = 0; i < 3; i++) {
        std::cout << static_cast<int>(obj.Reserved[i]) << " ";
    }
    std::cout << std::endl;
}

void CommunityCan::sendFrames(
        const QString &sendMode,
        const QString &frameType,
        const QString &frameFormat,
        const QString &frameId,
        const QString &frameDataLen,
        const QString &frameData,
        const QString &sendCount,
        const QString &sendInterval
) {
    // 在这里执行发送逻辑
    qDebug() << "发送方式:" << sendMode;
    qDebug() << "帧类型:" << frameType;
    qDebug() << "帧格式:" << frameFormat;
    qDebug() << "帧ID:" << frameId;
    qDebug() << "帧长度:" << frameDataLen;
    qDebug() << "帧数据:" << frameData;
    qDebug() << "发送次数:" << sendCount;
    qDebug() << "发送间隔(ms):" << sendInterval;

    CAN_OBJ frame;
    memset(&frame, 0, sizeof(frame));
    bool ok = false;
    frame.ID = frameId.toInt(&ok, 16);
    frame.DataLen = frameDataLen.toInt();
    // =0时为正常发送，=1时为单次发送（不自动重发），=2时为自发自收（用于测试CAN卡是否损坏），
    // =3时为单次自发自收（只发送一次，用于自测试），只在此帧为发送帧时有意义。
    frame.SendType = getSendMode(sendMode);
    // 是否是远程帧。=0时为数据帧，=1时为远程帧。
    frame.RemoteFlag = getFrameType(frameType);
    // 是否是扩展帧。 =0时为标准帧（11位帧ID）， =1时为扩展帧（29位帧ID）。
    frame.ExternFlag = getFrameFormat(frameFormat);
    // data payload 数据载荷
    QStringList hexList = frameData.split(" ");
    QVector<int> QData;
    for (int i = 0; i < hexList.size(); i++) {
        const QString &hex = hexList[i];
        bool ok;
        int value = hex.toInt(&ok, 16);
        if (ok) {
            if (i < 8) {
                frame.Data[i] = value;
                QData.append(value);
            } else {
                break;
            }
        } else {
            qDebug() << "Invalid hex number: " << hex;
        }
    }
    print_CAN_Obj(frame);
    qDebug() << "QData: " << QData;
    // 发送100次
    unsigned int transmitCount = Transmit(DeviceType, DeviceInd, CAN1, &frame, 100);
    if (transmitCount <= 0) {
        std::cout << "发送 can 数据失败: " << transmitCount << std::endl;
    } else {
        std::cout << "发送 can 数据成功: " << transmitCount << std::endl;
    }
}

void CommunityCan::stopSending() {
    // 在这里执行停止发送逻辑
    qDebug() << "停止发送";
}

/**
 * 关闭窗口的回调
 *
 * @param event 回调事件
 */
void CommunityCan::closeEvent(QCloseEvent *event) {
    // 窗口关闭时，我们关闭can设备，避免出现段错误
    CloseDevice(DeviceType, DeviceInd);
    QWidget::closeEvent(event);
}
